package net.phoenix.repository.nodetype;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;


/**
 * 
 * @author lixf
 * 
 */
public abstract class InheritedNodeTypeManager extends GeneralNodeTypeManager {
	private GeneralNodeTypeManager parent;

	/**
	 * @return the parent
	 */
	public NodeTypeManager getParent() {
		return parent;
	}

	/**
	 * @param parent
	 *            the parent to set
	 */
	public void setParent(NodeTypeManager parent) {
		this.parent = (GeneralNodeTypeManager) parent;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.phoenix.repository.definition.GeneralNodeDefinitionManager#definitions
	 * ()
	 */
	@SuppressWarnings("unchecked")
	public NodeTypeIterator getAllNodeTypes() {
		if (this.parent == null)
			return super.getAllNodeTypes();
		LinkedHashSet<NodeType> result = new LinkedHashSet<NodeType>();
		result.addAll(toList(super.getAllNodeTypes()));
		result.addAll(toList(this.parent.getAllNodeTypes()));
		return new BasicNodeTypeIterator(result);
	}

	@Override
	public NodeType getNodeType(String pkid) throws NoSuchNodeTypeException {
		if(pkid == null)
			throw new NullPointerException("node type name should not be null.");
		NodeType definition = null;
		try {
			definition = super.getNodeType(pkid);
		} catch (NoSuchNodeTypeException ex) {
			if (parent != null)
				definition = parent.getNodeType(pkid);
		}		
		if(definition == null)
			throw new NoSuchNodeTypeException(pkid);
		return definition;
	}
	 
    /**
     * Gets a list based on an iterator.
     * <p>
     * As the wrapped Iterator is traversed, an ArrayList of its values is
     * created. At the end, the list is returned.
     *
     * @param iterator  the iterator to use, not null
     * @return a list of the iterator contents
     * @throws NullPointerException if iterator parameter is null
     */
    public static List<NodeType> toList(Iterator<NodeType> iterator) {
        return toList(iterator, 10);
    }
    
    /**
     * Gets a list based on an iterator.
     * <p>
     * As the wrapped Iterator is traversed, an ArrayList of its values is
     * created. At the end, the list is returned.
     *
     * @param iterator  the iterator to use, not null
     * @param estimatedSize  the initial size of the ArrayList
     * @return a list of the iterator contents
     * @throws NullPointerException if iterator parameter is null
     * @throws IllegalArgumentException if the size is less than 1
     */
    public static  List<NodeType> toList(Iterator<NodeType> iterator, int estimatedSize) {
        if (iterator == null) {
            throw new NullPointerException("Iterator must not be null");
        }
        if (estimatedSize < 1) {
            throw new IllegalArgumentException("Estimated size must be greater than 0");
        }
        List<NodeType> list = new ArrayList<NodeType>(estimatedSize);
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }

}
